package org.helyx.gae.getabike.web.controller.api;

import java.io.IOException;
import java.util.List;

import org.apache.http.conn.ClientConnectionManager;
import org.helyx.gae.adapter.http.client.GAEConnectionManager;
import org.helyx.gae.getabike.content.accessor.HttpContentAccessor;
import org.helyx.gae.getabike.content.provider.exception.ContentProviderException;
import org.helyx.gae.getabike.model.City;
import org.helyx.gae.getabike.model.Station;
import org.helyx.gae.getabike.model.StationDetails;
import org.helyx.gae.getabike.provider.VelibStationContentProvider;
import org.helyx.gae.getabike.provider.details.VelibStationDetailsContentProvider;
import org.helyx.gae.getabike.provider.normalizer.StationInfoNormalizer;
import org.helyx.gae.getabike.registry.Registry;
import org.helyx.gae.getabike.text.StringFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class StationController implements InitializingBean {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(StationController.class);
	
	@Autowired
	Registry<String, City> cityRegistry;

	@Autowired
private Registry<String, StationInfoNormalizer> stationInfoNormalizerRegistry;

	public StationController() {
		super();
	}
	
	public void setCityRegistry(Registry<String, City> cityRegistry) {
		this.cityRegistry = cityRegistry;
	}
	
	public void setStationInfoNormalizerRegistry(Registry<String, StationInfoNormalizer> stationInfoNormalizerRegistry) {
		this.stationInfoNormalizerRegistry = stationInfoNormalizerRegistry;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(cityRegistry, "[Assertion failed] - cityRegistry is required; it must not be null");
		Assert.notNull(stationInfoNormalizerRegistry, "[Assertion failed] - stationInfoNormalizerRegistry is required; it must not be null");
	}

	@RequestMapping(value="/city/{city}/station/list", method = RequestMethod.GET)
	@ResponseBody
	public List<Station> getStationList(@PathVariable("city") String cityId) throws IOException, Exception {
		try {
	
	        City city = cityRegistry.get(cityId);
	        
	        if (city == null) {
	        	throw new NullPointerException("The city with key: '" + cityId + "' is not referenced");
	        }
	        
	        ClientConnectionManager clientConnectionManager = new GAEConnectionManager();
			HttpContentAccessor contentAccessor = new HttpContentAccessor(clientConnectionManager, city.getStationListUri());
			StationInfoNormalizer stationInfoNormalizer = stationInfoNormalizerRegistry.get(city.getNormalizer());
			
			VelibStationContentProvider velibStationContentProvider = new VelibStationContentProvider();
			velibStationContentProvider.setCity(city);
			velibStationContentProvider.setContentAccessor(contentAccessor);
			velibStationContentProvider.setStationInfoNormalizerRegistry(stationInfoNormalizerRegistry);
			velibStationContentProvider.afterPropertiesSet();
			
			List<Station> stationList = velibStationContentProvider.getContent();
			
			return stationList;	
		}
		catch (ContentProviderException e) {
			throw new IOException(e);
		}
    }
	
	@RequestMapping(value="/city/{city}/station/{station}", method = RequestMethod.GET)
	@ResponseBody
    public StationDetails getStationDetails(@PathVariable("city") String cityId, @PathVariable("station") String stationId) throws IOException, Exception {
        try {
	        City city = cityRegistry.get(cityId);
	        
	        if (city == null) {
	        	throw new NullPointerException("The city with key: '" + cityId + "' is not referenced");
	        }

	        ClientConnectionManager clientConnectionManager = new GAEConnectionManager();
	        String stationDetailsUri = new StringFormat(city.getStationDetailsUri()).format(stationId);
			HttpContentAccessor contentAccessor = new HttpContentAccessor(clientConnectionManager, stationDetailsUri);
			
			VelibStationDetailsContentProvider velibStationDetailsContentProvider = new VelibStationDetailsContentProvider();
			velibStationDetailsContentProvider.setCity(city);
			velibStationDetailsContentProvider.setContentAccessor(contentAccessor);
			velibStationDetailsContentProvider.afterPropertiesSet();

	        StationDetails stationDetails = velibStationDetailsContentProvider.getContent(stationId);

			return stationDetails;
		}
		catch (ContentProviderException e) {
			throw new IOException(e);
		}
    }
	
}
